package com.linq.cool.beauty.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.linq.cool.api.domain.BeautyMember;
import com.linq.cool.api.domain.BeautyMemberItem;
import com.linq.cool.beauty.domain.BeautyRefund;
import com.linq.cool.beauty.domain.BeautyTopUp;
import com.linq.cool.beauty.dto.BeautyRefundQueryDTO;
import com.linq.cool.beauty.mapper.BeautyRefundMapper;
import com.linq.cool.beauty.service.BeautyMemberItemService;
import com.linq.cool.beauty.service.BeautyMemberService;
import com.linq.cool.beauty.service.BeautyRefundService;
import com.linq.cool.beauty.service.BeautyTopUpService;
import com.linq.cool.beauty.vo.statistical.MonthlyRefundVO;
import com.linq.cool.common.constants.Constants;
import com.linq.cool.common.constants.UserConstants;
import com.linq.cool.common.core.exception.BusinessException;
import com.linq.cool.common.core.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @Author: yqlin
 * @Date: 2021/2/3 19:27
 * @Description:
 * @Version: 1.0.0
 */

@Service
public class BeautyRefundServiceImpl extends ServiceImpl<BeautyRefundMapper, BeautyRefund> implements BeautyRefundService {
    @Autowired
    private BeautyTopUpService beautyTopUpService;
    @Autowired
    private BeautyMemberService beautyMemberService;
    @Autowired
    private BeautyMemberItemService beautyMemberItemService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void refundSuccess(String refundId, String backPlatformId, Integer backType) {
        // 根据退费订单ID查询退费订单
        BeautyRefund refund = this.getById(refundId);
        //设置平台交易编号
        refund.setBackPlatformId(backPlatformId)
                // 设置退费类型
                .setBackType(backType)
                // 设置退费时间
                .setBackTime(new Date())
                // 修改订单状态
                .setStatus(UserConstants.StateEnum.ORDER_REFUND_STATUS_1.getCode())
                .setModifier(SecurityUtils.getUserId())
                .setGmtModified(new Date());
        // 更新退费订单状态
        this.updateById(refund);
        // 更新充值订单状态 部分退款的时候 要注意会更新一个rest_amount未退费的金额
        BeautyTopUp topUp = beautyTopUpService.getById(refund.getTopUpId());
        if (UserConstants.StateEnum.ORDER_REFUND_TYPE_0.getCode().equals(refund.getType())) {
            // 全额退费
            topUp.setStatus(UserConstants.StateEnum.ORDER_STATUS_4.getCode()).setRestAmount(BigDecimal.ZERO);
        } else {
            // 假如全部退费完了
            if (refund.getAmount().compareTo(topUp.getRestAmount()) == 0) {
                // 全额退费
                topUp.setStatus(UserConstants.StateEnum.ORDER_STATUS_4.getCode());
            } else {
                // 部分退费
                topUp.setStatus(UserConstants.StateEnum.ORDER_STATUS_5.getCode());
            }
            // 未退费金额
            topUp.setRestAmount(topUp.getRestAmount().subtract(refund.getAmount()));
        }
        topUp.setModifier(SecurityUtils.getUserId()).setGmtModified(new Date());
        beautyTopUpService.updateById(topUp);
        // 更新客户积分
        BeautyMember customer = beautyMemberService.getById(refund.getMemberId());
        customer.setAmount(customer.getAmount().subtract(refund.getAmount()))
                .setModifier(SecurityUtils.getUserId())
                .setGmtModified(new Date())
        ;
        beautyMemberService.updateById(customer);
        // 更新客户字表信息
        BeautyMemberItem customerItem = beautyMemberItemService.getOne(new LambdaQueryWrapper<BeautyMemberItem>()
                                                                               .eq(BeautyMemberItem::getMemberId, customer.getId())
        );
        if (null == customerItem) {
            throw new BusinessException("该客户不存在");
        }
        customerItem
                .setRefundCount(customerItem.getRefundCount() + 1)
                // 累计消费减去
                .setConsumeAmount(customerItem.getConsumeAmount().subtract(refund.getAmount()))
                // 退费金额加上
                .setRefundAmount(customerItem.getRefundAmount().add(refund.getAmount()))
                .setModifier(SecurityUtils.getUserId())
                .setGmtModified(new Date());
        beautyMemberItemService.updateById(customerItem);
    }

    @Override
    public IPage<BeautyRefund> listByPage(IPage<BeautyRefund> page, BeautyRefundQueryDTO dto) {
        return this.page(page, new LambdaQueryWrapper<BeautyRefund>()
                .like(StringUtils.checkValNotNull(dto.getId()), BeautyRefund::getId, dto.getId())
                .like(StringUtils.checkValNotNull(dto.getTopUpId()), BeautyRefund::getTopUpId, dto.getTopUpId())
                .like(StringUtils.checkValNotNull(dto.getMemberPhone()), BeautyRefund::getMemberPhone, dto.getMemberPhone())
                .like(StringUtils.checkValNotNull(dto.getMemberRealName()), BeautyRefund::getMemberRealName, dto.getMemberRealName())
                .eq(StringUtils.checkValNotNull(dto.getStatus()), BeautyRefund::getStatus, dto.getStatus())
                .eq(StringUtils.checkValNotNull(dto.getType()), BeautyRefund::getType, dto.getType())
                .eq(StringUtils.checkValNotNull(dto.getBackType()), BeautyRefund::getBackType, dto.getBackType())
                .between(StringUtils.checkValNotNull(dto.getParams().get(Constants.BEGIN_TIME)), BeautyRefund::getGmtCreate, dto.getParams().get(Constants.BEGIN_TIME), dto.getParams().get(Constants.END_TIME))
        );
    }

    @Override
    public MonthlyRefundVO statisticalMonthlyRefund() {
        List<Object> yearMonthList = new LinkedList<>();
        List<Object> totalAmountList = new LinkedList<>();
        List<Map<String, Object>> maps = baseMapper.statisticalMonthlyRefund();
        for (Map<String, Object> map : maps) {
            yearMonthList.add(map.get("year_month"));
            totalAmountList.add(map.get("total_amount"));
        }
        return new MonthlyRefundVO().setYearMonthList(yearMonthList).setTotalAmountList(totalAmountList);
    }
}
